//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/.
// 			VisualNovelToolkit		     /_/_/_/_/_/_/_/_/_/.
// Copyright ©2013 - Sol-tribe.	/_/_/_/_/_/_/_/_/_/.
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/.
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

public class ByteCodeReader : MonoBehaviour{

#if true
	static public int readString( byte[] array , int index ){		

// Int Length Version.
#if true
		int charNum = readInt( array , index );
		int startIndex = index + 4;
// Byte Length Version.		
#else	
		int charNum = array[ index ];
		int startIndex = index + 1;
#endif
		int len = charNum * 2;
//		Debug.Log( "ByteCodeReader:str len : " + len);
		byte[] dst = new byte[ len ];
		Array.Copy( array , startIndex , dst , 0 , len );
		VirtualMachine.loadedString = System.Text.Encoding.Unicode.GetString( dst );
//		Debug.Log( "the string:" + VirtualMachine.loadedString );
		return startIndex + len;
	}
#else
	// For Debugging.
	public string[] stringBuffer = new string[ 200 ];
	static private ByteCodeReader m_Instance;
	static private int bufferIndex;

	static public int readString( byte[] array , int index ){		
		int charNum = array[ index ];
		int startIndex = index + 1;		
		int len = charNum * 2;
		byte[] dst = new byte[ len ];
		Array.Copy( array , startIndex , dst , 0 , len );
		VirtualMachine.loadedString = System.Text.Encoding.Unicode.GetString( dst );
		if( m_Instance == null ){
			GameObject obj = new GameObject();
			m_Instance = obj.AddComponent<ByteCodeReader>();
			DontDestroyOnLoad( obj );
		}
		m_Instance.stringBuffer[ bufferIndex ] = VirtualMachine.loadedString;
		bufferIndex++;
		if( bufferIndex >= 200 ){
			bufferIndex = 0;
		}
		return startIndex + len;
	}
#endif		

    static public int readInt(byte[] array, int index) {
        return (array[index] << 24) | ((array[index + 1] & 0xff) << 16)
               | ((array[index + 2] & 0xff) << 8) | (array[index + 3] & 0xff);
    }
	
    static public int readShort(byte[] array, int index) {
        return (array[index] << 8) | (array[index + 1] & 0xff);
    }
		
	// Current Opcode.TABLE and  readTable...	
	static public int readTable( byte[] codes , int programCounter , ref Hashtable param ){		
		param = new Hashtable();	
		programCounter++;
		int count = codes[ programCounter ]; // TABLE KEYs Count MUST Be Within 255.
		programCounter++;		
		for( int i=0;i<count;i++){			
			programCounter = readString( codes , programCounter + 1 );
			string key = VirtualMachine.loadedString;
//			Debug.Log( "table key:" + key );
			programCounter = readString( codes , programCounter + 1 );
			string val = VirtualMachine.loadedString;
//			Debug.Log( "table key:" + key );
			param[ key ] = val;			
		}	
		
		return programCounter;
	}
	
	static public int readVar( byte[] codes , int programCounter , ref Hashtable param , ref System.Text.StringBuilder textBuild , bool stubIndentOption=false ){
		programCounter = readString( codes , programCounter + 2 );			
#if false					
		if( VirtualMachine.symbolTable.ContainsKey( VirtualMachine.loadedString ) ){
			string text = VirtualMachine.symbolTable[ VirtualMachine.loadedString ] as string;
			if( ! string.IsNullOrEmpty( text ) ){
				// Trim space.
				if( ! stubIndentOption ){
					text = text.Trim();					
				}					
//				textBuf += text;	
				textBuild.Append( text );
				VirtualMachine.loadedTextLiteralString = text;
			}
			else{					
				Hashtable tbl = VirtualMachine.symbolTable[ VirtualMachine.loadedString ] as Hashtable;				
				param = tbl;
			}
		}
		else{				
			ViNoDebugger.LogError( "Var name : " + VirtualMachine.loadedString + " NOT Found." );
		}	
#else
			// Append Word from FlagTable.
			ScenarioNode scenario = ScenarioNode.Instance;
			if( scenario != null && scenario.flagTable != null ){
				string word = scenario.flagTable.GetStringValue( VirtualMachine.loadedString );
				textBuild.Append( word );
				VirtualMachine.loadedTextLiteralString = word;
			}
#endif

		return programCounter;
	}	
/*	
	/// <summary>
	/// Reads the func.
	/// </summary>
	/// <returns>
	/// return the endpoint of this func.
	/// </returns>
	/// <param name='codes'>
	/// Codes.
	/// </param>
	/// <param name='programCounter'>
	/// Program counter is Now , Opcode.FUNC.
	/// </param>
	[ Obsolete ]
	static public int readFunc( byte[] codes , int programCounter , Dictionary<string,FuncInfo> functionTable ){		
		int retPos = readInt( codes , programCounter + 1 );			
		// Opcode.FUNC , Opcode.STRING , name.			
		programCounter = readString( codes , programCounter + 6 );
		if( ! VirtualMachine.loadedString.Equals( string.Empty ) ){
			FuncInfo info = new FuncInfo();
			info.m_PcEntry = programCounter;
			info.m_ReturnPos = retPos;
			functionTable[ VirtualMachine.loadedString ] = info;//programCounter;
		}
		
		// Now , Skip the  Inner code of function  .	
		programCounter = retPos + 1; 		
		return programCounter;
	}	
	
	static public int readReturn( byte[] code , Stack<int> callstack  ){
		int retPos = 100000;
		if( callstack.Count > 0 ){
			retPos = callstack.Pop();
		}
#if false
		else{
			pc = code.Length + 10;	// <==== DANGER !!!.
		}
#endif				
		return retPos;
	}
//*/	
		

}
